/*
 * Copyright (c) 2020 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package me.yokeyword.fragmentation.debug;

import me.yokeyword.fragmentation.ResourceTable;
import me.yokeyword.fragmentation.util.ResUtil;

import ohos.agp.components.BaseItemProvider;
import ohos.agp.components.Button;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.components.Image;
import ohos.agp.components.LayoutScatter;
import ohos.agp.components.ListContainer;
import ohos.agp.components.Text;
import ohos.agp.components.element.Element;
import ohos.agp.render.Paint;
import ohos.agp.text.Font;
import ohos.agp.utils.Color;
import ohos.agp.utils.TextAlignment;
import ohos.agp.window.dialog.CommonDialog;
import ohos.app.Context;

import java.util.ArrayList;
import java.util.Collections;

public class CustomDialog extends CommonDialog implements Component.ClickedListener, ListContainerAdapter.InternalListCallback {
    private ListContainer listContainer;
    final Builder builder;

    public enum DialogTAction {
        POSITIVE,
        NEUTRAL,
        NEGATIVE
    }

    private CustomDialog(Builder builder) {
        super(builder.getContext());
        this.builder = builder;
        ComponentContainer rootLayout = (ComponentContainer) LayoutScatter.getInstance(builder.getContext()).parse(getInflateLayout(builder), null, false);
        prepareDialogView(rootLayout, builder);
        setContentCustomComponent(rootLayout);
    }

    private void prepareDialogView(ComponentContainer rootLayout, Builder builder) {
        // Retrieve references to views
        Text tvTitle = ResUtil.getComponent(rootLayout, ResourceTable.Id_title);
        Image ivLogo = ResUtil.getComponent(rootLayout, ResourceTable.Id_icon);
        DirectionalLayout titleFrame = ResUtil.getComponent(rootLayout, ResourceTable.Id_titleFrame);
        Text tvContent = ResUtil.getComponent(rootLayout, ResourceTable.Id_content);
        listContainer = ResUtil.getComponent(rootLayout, ResourceTable.Id_listContainer);

        // Button views initially used by checkIfStackingNeeded()
        Button btnPositive = ResUtil.getComponent(rootLayout, ResourceTable.Id_btnPositive);
        Button btnNeutral = ResUtil.getComponent(rootLayout, ResourceTable.Id_btnNeutral);
        Button btnNegative = ResUtil.getComponent(rootLayout, ResourceTable.Id_btnNegative);

        // Don't allow the submit button to not be shown for input dialogs
        if (builder.inputCallback != null && builder.positiveText == null) {
            builder.positiveText = ResUtil.getString(builder.getContext(), ResourceTable.String_ok);
        }

        // Set up the initial visibility of action buttons based on whether or not text was set
        if (btnPositive != null) {
            btnPositive.setVisibility(builder.positiveText != null ? Component.VISIBLE : Component.HIDE);
        }
        if (btnNeutral != null) {
            btnNeutral.setVisibility(builder.neutralText != null ? Component.VISIBLE : Component.HIDE);
        }
        if (btnNegative != null) {
            btnNegative.setVisibility(builder.negativeText != null ? Component.VISIBLE : Component.HIDE);
        }

        if (ivLogo != null) {
            ivLogo.setVisibility(Component.VISIBLE);
            ivLogo.setImageElement(builder.icon);
        }

        Paint paint = new Paint();
        paint.setColor(new Color(Color.GRAY.getValue()));
        rootLayout.invalidate();

        // Setup title and title frame
        if (tvTitle != null) {
            tvTitle.setFont(builder.mediumFont);
            tvTitle.setTextColor(new Color(ResUtil.getColor(builder.getContext(), ResourceTable.Color_material_black)));
            tvTitle.setTextAlignment(TextAlignment.START);

            if (builder.title == null) {
                if (titleFrame != null) {
                    titleFrame.setVisibility(Component.HIDE);
                }
            } else {
                tvTitle.setText(builder.title.toString());
                if (titleFrame != null) {
                    titleFrame.setVisibility(Component.VISIBLE);
                }
            }
        }

        if (tvContent != null) {
            tvContent.setLineSpacing(0f, 1.2f);
            tvContent.setTextColor(new Color(ResUtil.getColor(builder.getContext(), ResourceTable.Color_md_gray)));
            tvContent.setTextAlignment(TextAlignment.START);

            if (builder.content != null) {
                tvContent.setText(builder.content.toString());
                tvContent.setVisibility(Component.VISIBLE);
            } else {
                tvContent.setVisibility(Component.HIDE);
            }
        }

        // Setup action buttons
        boolean textAllCaps = ResUtil.getBoolean(builder.getContext(), ResourceTable.Boolean_textAllCaps);
        if (null != builder.positiveText && btnPositive != null) {
            btnPositive.setTextColor(new Color(ResUtil.getColor(builder.getContext(), ResourceTable.Color_colorAccent)));
            btnPositive.setFont(builder.mediumFont);
            String text = builder.positiveText.toString() != null ? builder.positiveText.toString() : "";
            if (textAllCaps && !text.equals("")) {
                text = text.toUpperCase();
            }
            btnPositive.setText(text);
            btnPositive.setTextAlignment(TextAlignment.START);
            btnPositive.setTag(DialogTAction.POSITIVE);
            btnPositive.setClickedListener(this);
        }

        if (null != builder.negativeText && btnNegative != null) {
            btnNegative.setFont(builder.mediumFont);
            //negativeTextView.setTextInputType(1);
            String text = builder.negativeText.toString() != null ? builder.negativeText.toString() : "";
            if (textAllCaps && !text.equals("")) {
                text = text.toUpperCase();
            }
            btnNegative.setText(text);
            btnNegative.setTextColor(new Color(ResUtil.getColor(builder.getContext(), ResourceTable.Color_colorAccent)));
            btnNegative.setTextAlignment(TextAlignment.END);
            btnNegative.setTag(DialogTAction.NEGATIVE);
            btnNegative.setClickedListener(this);
        }

        if (null != builder.neutralText && btnNeutral != null) {
            btnNeutral.setFont(builder.mediumFont);
            String text = builder.neutralText.toString() != null ? builder.neutralText.toString() : "";
            if (textAllCaps && !text.equals("")) {
                text = text.toUpperCase();
            }
            btnNeutral.setText(text);
            btnNeutral.setTextColor(new Color(ResUtil.getColor(builder.getContext(), ResourceTable.Color_colorAccent)));
            btnNeutral.setTextAlignment(TextAlignment.CENTER);
            btnNeutral.setTag(DialogTAction.NEUTRAL);
            btnNeutral.setClickedListener(this);
        }

        if (listContainer != null && builder.baseItemProvider == null) {
            builder.baseItemProvider = new ListContainerAdapter(this, builder.getContext());
        }

        invalidateList();
    }

    @Override
    public void onClick(Component component) {
        hide();
    }

    @Override
    public boolean onItemSelected(CustomDialog dialog, Component itemView, int position, CharSequence text, boolean longPress) {
        if (builder.autoDismiss) {
            // If auto dismiss is enabled, dismiss the dialog when a list item is selected
            hide();
        }
        if (!longPress && builder.listCallback != null) {
            builder.listCallback.onSelection(this, itemView, position, builder.items.get(position));
        }
        return true;
    }

    public static class Builder {
        private Context context;
        InputCallback inputCallback;
        ArrayList<CharSequence> items;
        BaseItemProvider baseItemProvider;
        CharSequence positiveText, neutralText, negativeText, title, content;
        Element icon;
        Font regularFont, mediumFont;
        ListCallback listCallback;
        boolean autoDismiss = true;

        public Builder(Context context) {
            this.context = context;

            if (this.mediumFont == null) {
                try {
                    this.mediumFont = new Font.Builder("sans-serif-medium").build();
                    this.mediumFont = Font.DEFAULT;
                } catch (Throwable ignored) {
                    this.mediumFont = Font.DEFAULT_BOLD;
                }
            }
            if (this.regularFont == null) {
                try {
                    this.mediumFont = new Font.Builder("sans-serif").build();
                    this.mediumFont = Font.DEFAULT;
                } catch (Throwable ignored) {
                    this.regularFont = Font.SANS_SERIF;
                    if (this.regularFont == null) {
                        this.regularFont = Font.DEFAULT;
                    }
                }
            }
        }

        public final Context getContext() {
            return context;
        }

        public Builder title(int titleRes) {
            this.title = ResUtil.getString(context, titleRes);
            return this;
        }

        public Builder icon(int iconRes) {
            this.icon = ResUtil.getPixelMapDrawable(context, iconRes);
            return this;
        }

        public Builder content(int contentRes) {
            this.content = ResUtil.getString(context, contentRes);
            return this;
        }

        public Builder items(CharSequence... items) {
            this.items = new ArrayList<>();
            Collections.addAll(this.items, items);
            return this;
        }

        public Builder positiveText(int positiveRes) {
            if (positiveRes == 0) {
                return this;
            }
            this.positiveText = ResUtil.getString(context, positiveRes);
            return this;
        }

        public void show() {
            new CustomDialog(this).setSize(1000, ComponentContainer.LayoutConfig.MATCH_CONTENT).show();
        }
    }

    public interface ListCallback {
        void onSelection(CustomDialog dialog, Component itemView, int position, CharSequence text);
    }

    public interface InputCallback {
    }

    private int getInflateLayout(Builder builder) {
        return ResourceTable.Layout_uilayouts_stack_layout;
    }

    private void invalidateList() {
        if (listContainer == null) {
            return;
        } else if ((builder.items == null || builder.items.size() == 0) && builder.baseItemProvider == null) {
            return;
        }
        listContainer.setItemProvider(builder.baseItemProvider);
        ((ListContainerAdapter) builder.baseItemProvider).setCallback(this);
    }
}
